package com.servlet;
import android.content.res.AssetManager;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import com.dev.MainActivity;
import com.log;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Stack;
import java.util.ArrayList;
import java.io.PrintStream;
import java.io.OutputStream;
import java.io.BufferedReader;
import java.io.BufferedInputStream;
import java.io.InputStreamReader;
import java.io.FileInputStream;
import android.widget.Magnifier.Builder;
import java.io.IOException;

public class HttpServer extends Thread {
    MainActivity ma;
    public int maxSession=2;
    public ArrayList<NetSession> sessions=new ArrayList<NetSession>();
    public File root;
    public File err404;
    public File err400;
    public File err403;
    public File indexHtml;
    public String inet;
    public volatile ServerSocket serverSocket;
    public volatile int state;
    public volatile Socket client;
    public HttpServer(MainActivity ma){
        this.ma=ma;
        root=ma.getDir("server",0);
        indexHtml=new File(root,"index.html");
        if(!indexHtml.exists()){
            LoadServerAsset lsa=new LoadServerAsset();
            lsa.start();            
        }
    }
    public static String ip2string(byte[] ip){
        if(ip.length==4){
            StringBuilder inetString=new StringBuilder();
            inetString.append(Byte.toUnsignedInt(ip[0])+".");
            inetString.append(Byte.toUnsignedInt(ip[1])+".");
            inetString.append(Byte.toUnsignedInt(ip[2])+".");
            inetString.append(Byte.toUnsignedInt(ip[3]));
            return inetString.toString();
        }else if(ip.length==6){
            StringBuilder inetString=new StringBuilder();
            inetString.append(Byte.toUnsignedInt(ip[0])+".");
            inetString.append(Byte.toUnsignedInt(ip[1])+".");
            inetString.append(Byte.toUnsignedInt(ip[2])+".");
            inetString.append(Byte.toUnsignedInt(ip[3])+".");
            inetString.append(Byte.toUnsignedInt(ip[4])+".");
            inetString.append(Byte.toUnsignedInt(ip[5]));
            log.alert("ipv6");
            return inetString.toString();

        }
        log.alert("length:"+ip.length);
        return null;
	}
    @Override
    public void run() {
        super.run();
        state=1;
        WifiInfo wi=ma.getSystemService(WifiManager.class).getConnectionInfo();

        for(int i=1024;true;i++){
            try{
                serverSocket=new ServerSocket(i);
                if(i>2000){
                    log.alert("open trans endpoint failed");
                    return;
                }
                break;
            }catch(Exception e){
                continue;
            }
		}
        inet=ip2string(ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(wi.getIpAddress()).array())+":"+serverSocket.getLocalPort();
        state=2;
        try{
            client=serverSocket.accept();
            NetSession session=new NetSession(client);
            sessions.add(session);
            session.start();
        }catch(Exception e){
            if(!serverSocket.isClosed()){
                log.alert("On waiting for client",e.toString());
            }
        }
    }
    class NetSession extends Thread{
        Socket client;
        InputStream is;
        InputStreamReader isr;
        OutputStream os;
        NetSession(Socket client){
            this.client=client;
            try{
                is=client.getInputStream();
                os=client.getOutputStream();
                isr=new InputStreamReader(is);
            }catch(Exception e){
                log.alert(e.toString());
            }
        }
        StringBuilder clientRequest=new StringBuilder();
        StringBuilder line=new StringBuilder();
        @Override
        public void run() {
            super.run();
            if(client.isInputShutdown()){
                postFile(null,-1,-1,0);
                return;
            }
            while(!interrupted()){
                try{
                    String header=readline();
                    if(header==null)return;
                    header=header.trim();
                    int sp=header.indexOf(' ');
                    if(sp>0){
                        String method=header.substring(0,sp);
                        if(method.equals("GET")){
                            String path=getPart(header,sp);
                            
                            int a=-1,b=-1;
                            for(String para=readline();;para=readline()){
                                if(para==null){
                                    postFile(path,a,b,0);
                                    client.close();
                                    return;
                                }else if(para.equals("\n")){
                                    postFile(path,a,b,0);
                                    break;
                                }
                            }
                        }else if(method.equals("HEAD")){
                            String path=getPart(header,sp);
                            skipRequest();
                            postFile(path,-1,-1,1);
                        }else{
                            post400(header);
                        }
                    }else{
                        post400(header);
                        client.close();
                        return;
                    }
                }catch(Exception e){
                    return;
                }
            }
        }
        void post400(String msg){
            
        }
        String filePath;
        String action;
        
        void parsePath(String s){
            int ques=s.indexOf('?');
            if(ques>=0){
                filePath=s.substring(0,ques);
                for(int index=ques+1;index<s.length();index++){
                    char ch=s.charAt(index);
                    if(ch=='a'){
                        
                    }
                }
            }else{
                filePath=s;
                action=null;
            }
        }
        void skipRequest()throws IOException{
            for(int n=isr.read();n>=0;){
                char ch=(char)n;
                if(ch=='\n'){
                    if((n=isr.read())>=0){
                        ch=(char)n;
                        if(ch=='\n'){
                            return;
                        }
                    }else return;
                }
            }
        }
        String getPart(String s,int index){
            int offs=index;
            for(;offs<s.length();offs++){
                char ch=s.charAt(offs);
                if(ch==' '){
                    break;
                }else if(ch=='\n'){
                    break;
                }
            }
            return s.substring(index,offs);
        }
        String readline()throws IOException{
            StringBuilder line=new StringBuilder();
            int n=isr.read();
            if(n<0)return null;
            for(;;){
                if(n>=0){
                    char ch=(char)n;
                    line.append(ch);
                    if(ch=='\n'){
                        return line.toString();
                    }
                }else{
                    break;
                }
            }
            return line.toString();
        }
        String h200="HTTP/1.1 200 OK\n";
        String cl="Content-Length:";
        String ct1="Content-Type:text/html;charset=utf-8";
        void postFile(String path,int start,int end,int intend){
            if(path==null){
                try{
                    FileInputStream fis=new FileInputStream(indexHtml);
                    byte[] buffer=new byte[1024];
                    String header=cl+indexHtml.length()+"\n"+ct1+"\n\n";
                    os.write(header.getBytes());
                    os.flush();
                    if(intend==0){
                        int len=is.read(buffer);
                        while(len>0){
                            os.write(buffer,0,len);
                            len=is.read(buffer);
                        }
						os.flush();
                    }
                    fis.close();
                }catch(Exception e){}
            }else{
                if(path.contains("..")){
                    post404(path);
                }else{
                    try{
                        sleep(100);
                        File file=new File(root,path);
                        if(file.exists()){
                            if(file.isFile()){
                                FileInputStream fis=new FileInputStream(file);
                                byte[] buffer=new byte[1024];
                                String header=cl+file.length()+"\n\n";
                                os.write(header.getBytes());
                                if(intend==0){
                                    int len=fis.read(buffer);
                                    while(len>0){
                                        os.write(buffer,0,len);
                                        len=is.read(buffer);
                                    }
                                    os.flush();
                                }
                                fis.close();
                            }else{
                                post404(path);
                            }
                        }else post404(path);
                    }catch(Exception e){}
                }
            }
        }
        void post404(String rawRequest){
            
        }
    }
    public class LoadServerAsset extends Thread {
        @Override
        public void run() {
            super.run();
            AssetManager am=ma.getAssets();
            try{
                Stack<String> stack=new Stack<String>();
                String[] list=am.list("server");
                byte[] buffer=new byte[1024];
                while(true){
                    for(int index=0;index<list.length;index++){
                        String name=list[index];
                        if(name.charAt(name.length()-1)=='/'){
                            stack.push(name);
                            File newdir=new File(root,name);
                            newdir.mkdir();
                        }else{
                            File newFile=new File(root,name);
                            InputStream is=am.open(name);
                            FileOutputStream fos=new FileOutputStream(newFile);
                            int len=is.read(buffer);
                            while(len>0){
                                fos.write(buffer,0,len);
                                len=is.read(buffer);
                            }
                            fos.close();
                            is.close();
                        }
                    }
                    if(stack.isEmpty()){break;}else{list=am.list(stack.pop());}
                }
            }catch(Exception e){
                log.alert("When loading resources of servlet files async",e.toString());
            }
        }
        
    }
}
